﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using COFE.Core.Profile;
using COFE.Core.Lister;
using COFE.Core;
using COFE.Core.Utils;
using NUnit.Framework;

namespace COFE.Core
{
    public static class IUserProfileExtension
    {
        #region DirectoryLister

        /// <summary>
        /// Register in registrar, then register it in manager.
        /// accessMode is ignored for secondary volumes.
        /// </summary>
        /// <param name="profile"></param>
        /// <param name="volume"></param>
        /// <param name="accessMode"></param>
        public static void RegisterVolume(this IUserProfile profile, IDirectoryLister lister, VolumeAccessMode accessMode = VolumeAccessMode.All)
        {
            if (lister.Factory == null)
            {
                COFEShared.VolumeRegistrar.RegisterVolume(COFEShared.VolumeRegistrar.ConstructVolume(null, lister, accessMode));
                profile.Volumes.RegisterVolume(lister.ListerKey);
            }
            else
            {
                Assert.IsNotNullOrEmpty(lister.Factory.FactoryKey);
                COFEShared.VolumeRegistrar.RegisterVolume(COFEShared.VolumeRegistrar.ConstructVolume(lister.Factory.FactoryKey,
                    lister, accessMode));
                profile.Volumes.RegisterVolume(lister.ListerKey);
            }
        }

        public static void RegisterFactory(this IUserProfile profile, IFactory<IDirectoryLister> factory)
        {
            FactoryRegister<IDirectoryLister>.RegisterFactory(factory.FactoryKey, factory);
            //profile.VolumeRegistrar.RegisterFilter(factory);
        }

        public static void RegisterVolume(this IUserProfile profile, string factoryKey, string listerKey,
            string paramString, VolumeAccessMode accessMode = VolumeAccessMode.All)
        {
            var vol = COFEShared.VolumeRegistrar.ConstructVolume(factoryKey, listerKey, paramString, accessMode);
            COFEShared.VolumeRegistrar.RegisterVolume(vol);
            profile.Volumes.RegisterVolume(listerKey);
        }

        /// <summary>
        /// Calls profile.Volumes.RegisterVolume(volumeKey)
        /// </summary>
        /// <param name="profile"></param>
        /// <param name="volumeKey"></param>
        public static void RegisterVolume(this IUserProfile profile, string volumeKey)
        {
            profile.Volumes.RegisterVolume(volumeKey);
        }

        public static IVolume FindRegisteredVolume(this IUserProfile profile, string listerKey)
        {
            return profile.Volumes.FindRegisteredVolume(listerKey);
        }

        public static IVolume[] FindRegisteredVolume<T>(this IUserProfile profile)
        {
            return profile.Volumes.FindRegisteredVolume<T>();
        }

        #endregion

        #region Path Parsing

        public static IFileSystemInfo ParseGuid(this IUserProfile profile, Guid guid)
        {
            IFileSystemInfo retVal = profile.TryParseGuid(guid);
            if (retVal == null)
                throw new KeyNotFoundException(guid.ToString());
            return retVal;
        }

        public static IFileSystemInfo TryParseGuid(this IUserProfile profile, Guid guid,
            EntryConstructionFlags flags = EntryConstructionFlags.Default)
        {
            return COFEShared.PathParser.TryParsePath(profile, guid.ToString(), ParsableType.Guid, flags);
        }

        public static IFileSystemInfo ParsePath(this IUserProfile profile, string path, string listerKey)
        {
            return profile.ParsePath(COFEPath.FormatFullParseName(listerKey, path));
        }

        public static IFileSystemInfo ParsePath(this IUserProfile profile, string path, 
            EntryConstructionFlags flags = EntryConstructionFlags.Default)
        {
            IFileSystemInfo retVal = profile.TryParsePath(path, flags);
            if (retVal == null)
                throw new System.IO.FileNotFoundException(path);
            return retVal;
        }

        /// <summary>
        /// Call ParsePath with flags = DefaultWithoutCacheWithLookup
        /// </summary>
        /// <param name="profile"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public static IFileSystemInfo ParseNonCachePath(this IUserProfile profile, string path)
        {
            return profile.ParsePath(path, EntryConstructionFlags.DefaultWithoutCacheWithLookup);
        }

        public static IFileSystemInfo TryParseNonCachePath(this IUserProfile profile, string path)
        {
            return profile.TryParsePath(path, EntryConstructionFlags.DefaultWithoutCacheWithLookup);
        }

        public static IFileSystemInfo TryParsePath(this IUserProfile profile, string path, string listerKey)
        {
            return profile.TryParsePath(COFEPath.FormatFullParseName(listerKey, path));
        }

        public static IFileSystemInfo TryParsePath(this IUserProfile profile, string path,
            EntryConstructionFlags flags = EntryConstructionFlags.DefaultWithLookup)
        {
            return COFEShared.PathParser.TryParsePath(profile, path, ParsableType.ParsePath, flags);
        }

        public static IFileSystemInfo TryLookupPath(this IUserProfile profile, string path, string listerKey)
        {
            return profile.TryLookupPath(COFEPath.FormatFullParseName(listerKey, path));
        }

        public static IFileSystemInfo TryLookupPath(this IUserProfile profile, string path)
        {
            return COFEShared.PathParser.TryParsePath(profile, path, ParsableType.ParsePathLookup);
        }

        #endregion
    }
}
